<?php
/**
 * Config       系统核心
 * @copyright   Copyright(c) 2024-2034
 * @author      tianjie <527707665@qq.com>
 * @link        http://www.tinphp.com/
 * @version     4.1
 */

namespace tian;

class Config
{
    /**
     * @var array 配置参数
     */
    private $config = [];

    /**
     * @var string 参数作用域
     */
    private $range = '';

    /**
     * 设定配置参数的作用域
     * @param $range
     * @return void
     */
    public function range($range)
    {
        $this->range = $range;
        if (!isset($this->config[$range])) {
            if (!empty($range)) {
                $this->config[$range] = [];
            }
        }
    }

    /**
     * 加载配置文件（PHP格式）
     * @access public
     * @param string $file 配置文件名
     * @param string $name 配置名（如设置即表示二级配置）
     * @param string $range 作用域
     * @return mixed
     */
    public function load(string $file, string $name = '', string $range = '')
    {
        $range = $range ?: $this->range;
        if (!isset($this->config[$range])) {
            if (!empty($range)) {
                $this->config[$range] = [];
            }
        }

        if (is_file($file)) {
            $name = strtolower($name);
            $type = pathinfo($file, PATHINFO_EXTENSION);

            if ('php' == $type) {
                return $this->set(include $file, $name, $range);
            }
        }

        if (!empty($range)) {
            return $this->config[$range];
        } else {
            return $this->config;
        }
    }

    /**
     * 检测配置是否存在
     * @param $name
     * @param string $range
     * @return bool
     */
    public function has($name, string $range = ''): bool
    {
        $range = $range ?: $this->range;

        if (!strpos($name, '.')) {
            return isset($this->config[$range][strtolower($name)]);
        }

        // 二维数组设置和获取支持
        $name = explode('.', $name, 2);
        if (!empty($range)) {
            return isset($this->config[$range][strtolower($name[0])][$name[1]]);
        } else {
            return isset($this->config[strtolower($name[0])][$name[1]]);
        }
    }

    /**
     * 获取配置参数 为空则获取所有配置
     * @param string|null $name 配置参数名（支持二级配置 . 号分割）
     * @param string $range 作用域
     * @return mixed|null
     */
    public function get(string $name = null, string $range = '')
    {
        $range = $range ?: $this->range;

        // 无参数时获取所有
        if (empty($name) && isset($this->config[$range])) {
            return $this->config[$range];
        }

        $name = strtolower($name);
        if (!empty($range)) {
            return $this->config[$range][$name] ?? $this->config;
        } else {
            return $this->config[$name] ?? $this->config;
        }
    }

    /**
     * 设置配置参数 name 为数组则为批量设置
     * @param string|array $name 配置参数名（支持二级配置 . 号分割）
     * @param mixed $value 配置值
     * @param string $range 作用域
     * @return array|mixed|null
     */
    public function set($name, $value = null, string $range = '')
    {
        $range = $range ?: $this->range;
        if (!isset($this->config[$range])) {
            if (!empty($range)) {
                $this->config[$range] = [];
            }
        }

        // 字符串则表示单个配置设置
        if (is_string($name)) {
            if (!strpos($name, '.')) {
                if (!empty($range)) {
                    $this->config[$range][strtolower($name)] = $value;
                } else {
                    $this->config[strtolower($name)] = $value;
                }
            } else {
                // 二维数组
                $name = explode('.', $name, 2);
                if (!empty($range)) {
                    $this->config[$range][strtolower($name[0])][$name[1]] = $value;
                } else {
                    $this->config[strtolower($name[0])][$name[1]] = $value;
                }
            }

            return $value;
        }

        // 数组则表示批量设置
        if (is_array($name)) {
            if (!empty($value)) {
                if (!empty($range)) {
                    $this->config[$range][$value] = isset($this->config[$range][$value]) ? array_merge($this->config[$range][$value], $name) : $name;
                    return $this->config[$range][$value];
                } else {
                    $this->config[$value] = isset($this->config[$value]) ? array_merge($this->config[$value], $name) : $name;
                    return $this->config[$value];
                }

            }

            if (!empty($range)) {
                //return $this->config[$range] = array_merge($this->config[$range], array_change_key_case($name));

                if (isset($this->config[$range]) && empty($this->config[$range])) {
                    $this->config[$range] = $name;
                } else {
                    foreach ($this->config[$range] as $key => $value) {
                        if (is_array($value)) {
                            foreach ($value as $k => $v) {
                                if (is_array($v)) {
                                    $this->config[$range][$key][$k] = !empty($v) && !empty($name[$key][$k]) ? array_merge($v, $name[$key][$k]) : (!empty($v) ? $v : $name[$key][$k]);
                                } else {
                                    $this->config[$range][$key][$k] = !empty($name[$key][$k]) ? $name[$key][$k] : $v;
                                }
                            }
                        } else {
                            $this->config[$range][$key] = !empty($name[$key]) ? $name[$key] : $value;
                        }
                    }
                }

                return $this->config[$range];
            } else {
                return $this->config = array_merge($this->config, array_change_key_case($name));
            }
        }

        // 为空直接返回已有配置
        if (!empty($range)) {
            return $this->config[$range];
        } else {
            return $this->config;
        }
    }

    /**
     * 重置配置参数
     * @param string $range 作用域
     * @return void
     */
    public function reset(string $range = '')
    {
        $range = $range ?: $this->range;

        if ($range) {
            $this->config = [];
        } else {
            $this->config[$range] = [];
        }
    }
}
